using System;
using System.Collections.Generic;
using System.IO;
using ACS.Compiler.Grammar.Impl;
using ACS.Compiler.Tables;
using ACS.Compiler.Tree;
using ACS.Compiler.Tree.Impl;
using ACS.Compiler.Util;
using antlr.collections;

namespace ACS.Compiler.Parser
{

    public class FileParser
    {
        private string _fileName;

        private string _moduleName;

        private static FileParser _currentFileParser;

        private static Dictionary<string, FileParser> CahedFileParsers = 
            new Dictionary<string, FileParser>();

        public static FileParser CurrentFileParser
        {
            get
            {
                return _currentFileParser;
            }
        }

        public static FileParser ParserByName(string moduleName)
        {
            FileParser ret;
            CahedFileParsers.TryGetValue(moduleName, out ret);
            if (ret == null && CurrentFileParser.ModuleName == moduleName)
            {
                return CurrentFileParser;
            }
            return ret;
        }

        public static bool IsNamespace(string ident)
        {
            if (ident == null)
            {
                return false;
            }
            return CahedFileParsers.ContainsKey(ident) || CurrentFileParser.ModuleName == ident;
        }

        public static FileParser InitializeParser(string fileName)
        {
            if (_currentFileParser != null)
            {
                CahedFileParsers.Add(_currentFileParser.ModuleName, _currentFileParser);
            }
            _currentFileParser = new FileParser(fileName);
            return _currentFileParser; 
        }

        private FileParser(string fileName)
        {
            _fileName = fileName;
            FileInfo info = new FileInfo(fileName);
            _moduleName = info.Name;
            int pos = _moduleName.IndexOf('.');
            if (pos > 0)
            {
                _moduleName = _moduleName.Substring(0, pos);
            }
            _moduleName = _moduleName.ToLower();
            _moduleName = Char.ToUpper(_moduleName[0]) + _moduleName.Substring(1, _moduleName.Length - 1);
        }

        private TreeBase _ast;
        private Module _module;

        ErrorsTrace _errors = new ErrorsTrace();

        public ErrorsTrace Errors
        {
            get
            {
                return _errors;
            }
        }

        public void Parse()
        {
            try
            {
                AcsLexer lexer =
                    new AcsLexer(File.OpenText(_fileName));
                AcsParser parser = new AcsParser(lexer);
                parser.setASTNodeClass("ACS.Compiler.Tree.TreeBase");
                parser.mprogram();
                _ast = parser.getAST();
                _module = (Module)_ast;
                _ast.Build();
            }
            catch (Exception e)
            {
                Logger.Instance.TraceError(e.Message); 
            }
        }

        public static void TreePrint(AST ast, int level)
        {
            AST sib = ast;
            while (sib != null)
            {
                Console.WriteLine(new String(' ',level) + sib.ToString());
                TreePrint(sib.getFirstChild(), level + 1);
                sib = sib.getNextSibling(); 
            }
        }


        public string ModuleName
        {
            get { return _moduleName; }
        }

        public Module Module
        {
            get { return _module; }
        }
    }
}
